一、pipe
概念
pipe 是nio管道2个线程之前的单项数据连接。
pipe 有2个通道一个是source通道一个是sink通道
数据会写入到source通道从sink通道获取数据。如图:
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class PipeTest { public static void main(String[] args) {
Pipe pipe = null; ExecutorService exec = Executors.newFixedThreadPool(2); try { pipe = Pipe.open(); final Pipe pipeTemp = pipe; exec.submit(new Callable<Object>() { @Override public Object call() throws Exception { Pipe.SinkChannel sinkChannel = pipeTemp.sink();//向通道中写 while (true) { TimeUnit.SECONDS.sleep(1); String newData = "Pipe Test At Time " + System.currentTimeMillis(); ByteBuffer buf = ByteBuffer.allocate(1024); buf.clear(); buf.put(newData.getBytes()); buf.flip(); while (buf.hasRemaining()) { System.out.println(buf); sinkChannel.write(buf); } } } }); exec.submit(new Callable<Object>() { @Override public Object call() throws Exception {Pipe.SourceChannel sourceChannel = pipeTemp.source();//向 while (true) { TimeUnit.SECONDS.sleep(1); ByteBuffer buf = ByteBuffer.allocate(1024); buf.clear(); int bytesRead = sourceChannel.read(buf); System.out.println("bytesRead=" + bytesRead); while (bytesRead > 0) { buf.flip(); byte b[] = new byte[bytesRead]; int i = 0; while (buf.hasRemaining()) { b[i] = buf.get(); System.out.printf("%X", b[i]); i++; } String s = new String(b); System.out.println("=================||" + s); bytesRead = sourceChannel.read(buf); }
|
二、FileChannel文件锁
在通道中我们可以对文件或者部分文件进行上锁。上锁和我们了解的线程锁差不多,都是为 了保证数据的一致性。在文件通道 FileChannel 中可以对文件进行上锁,通过 FileLock 可以 对文件进行锁的释放。 文件加锁是建立在文件通道(FileChannel)之上的,套接字通道(SockeChannel)不考虑文 件加锁,因为它是不共享的。
它对文件加锁有两种方式:
- lock
- tryLock
两种加锁方式默认都是对整个文件加锁,如果自己配置的话就可以控制加锁的文件范围: position 是加锁的开始位置,size 是加锁长度,shared 是用于控制该锁是共享的还是独占的。
- lock 是阻塞式的,当有进程对锁进行读取时会等待锁的释放,在此期间它会一直等待;
- tryLock 是非阻塞式的,它尝试获得锁,如果这个锁不能获得,那么它会立即返回。
release 可以释放锁。
在一个进程中在锁没有释放之前是无法再次获得锁的
在 java 的 NIO 中,通道包下面有一个 FileLock 类,它主要是对文件锁工具的一个描述。在 上一小节中对文件的锁获取其实是 FileChannel 获取的(lock 与 trylock 是 FileChannel 的方 法),它们返回一个 FileLock 对象。
这个类的核心方法有如下这些:
boolean isShared() :判断锁是否为共享类型
abstract boolean isValid() :判断锁是否有效
boolean overlaps():判断此锁定是否与给定的锁定区域重叠 long position():返回文件内锁定区域中第一个字节的位置。
abstract void release() :释放锁
long size() :返回锁定区域的大小,以字节为单位
在文件锁中有 3 种方式可以释放文件锁:
- 锁类释放锁,调用 FileLock 的 release 方法
- 通道类关闭通道,调用 FileChannel 的 close 方法
- jvm 虚拟机会在特定情况释放锁。
锁类型(独占式和共享式)
我们先区分一下在文件锁中两种锁的区别:
- 独占式的锁就想我们上面测试的那样,只要有一个进程获取了独占锁,那么别的进程只能等待。
- 共享锁在一个进程获取的情况下,别的 进程还是可以读取被锁定的文件,但是别的进程不能写只能读。